package lu.uni.adtool.adtree;

import java.awt.FontMetrics;
import java.awt.Point;
import java.awt.Toolkit;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import org.abego.treelayout.NodeExtentProvider;

import lu.uni.adtool.Options;

import lu.uni.adtool.ui.ADTreeCanvas;
import lu.uni.adtool.ui.DomainCanvas;

/**
 * A {@link NodeExtentProvider} for nodes of type {@link TextInBox}.
 * <p>
 * As one would expect this NodeExtentProvider returns the width and height as
 * specified with each TextInBox.
 * 
 * @author Piotr Kordy
 */
public class ADTreeNodeExtentProvider implements NodeExtentProvider<ADTreeNode>
{
  /**
   * List of canvas that have common size of node with main canvas.
   */
  private final static int X_PADDING = 25;
  private final static int Y_PADDING = 15;
  private Set<DomainCanvas<?>> canvasSet; 
  private ADTreeCanvas owner;
  private HashMap<ADTreeNode, Point> sizes; 
  
  /**
   * Constructs a new instance.
   */
  public ADTreeNodeExtentProvider()
  {
    canvasSet = new HashSet<DomainCanvas<?>>();
    sizes = new HashMap<ADTreeNode, Point>();
    owner = null;
  }

  public void registerCanvas(DomainCanvas<?> canvas)
  {
    canvasSet.add(canvas);
  }
  public void deregisterCanvas(DomainCanvas<?> canvas)
  {
    canvasSet.remove(canvas);
  }
  /**
   * {@inheritDoc}
   * @see NodeExtentProvider#getWidth(ADTreeNode)
   */
  public final double getWidth(final ADTreeNode node)
  {
    return sizes.get(node).x;
  }

  /**
   * {@inheritDoc}
   * @see NodeExtentProvider#getHeight(ADTreeNode)
   */
  public final double getHeight(final ADTreeNode node)
  {
    return sizes.get(node).y;
  }
  /**
   * Deletes all calculated sizes.
   * @param node
   * 
   */
  public final void clearSizes()
  {
    sizes.clear();
  }
  /**
   * Calculates new size for the node.
   * @param node
   * 
   */
  public final void updateSize(final ADTreeNode node)
  {
    String label = owner.getLabel(node);
    Point size = getSizeOfText(label);
    for (ADTreeCanvas canvas: canvasSet){
      label = canvas.getLabel(node);
      Point newSize = getSizeOfText(label);
      size.x = Math.max(size.x,newSize.x);
      size.y = Math.max(size.y,newSize.y);
    }
    sizes.put(node,size);

  }
  /**
   * Splits text to lines and calculates the size.
   * 
   * @param label
   */
  private final Point getSizeOfText(String label)
  {
    final FontMetrics m = Toolkit.getDefaultToolkit().getFontMetrics(
        Options.canv_Font);
    String result = "";
    String[] lines = label.split(System.getProperty("line.separator"));
    for (String line:lines){
      if(line.length()>result.length()){
        result = line;
      }
    }
    return new Point(m.stringWidth(result)+X_PADDING,m.getHeight()*lines.length+Y_PADDING);
  }
  /**
   * Sets the owner for this instance.
   *
   * @param owner The owner.
   */
  public void setOwner(ADTreeCanvas owner)
  {
    if (this.owner == null && owner!=null){
      this.owner = owner;
    }
  }

  /**
   * Gets the sizes for this instance.
   *
   * @return The sizes.
   */
  public HashMap<ADTreeNode, Point> getSizes()
  {
    return this.sizes;
  }

  /**
   * Gets the owner for this instance.
   *
   * @return The owner.
   */
  public ADTreeCanvas getOwner()
  {
    return this.owner;
  }
}
